package team.cdlzz.controller;


import com.alibaba.fastjson.JSONObject;
import org.springframework.stereotype.Controller;
import team.cdlzz.dao.UserMapper;
import team.cdlzz.model.pojo.User;
import team.cdlzz.model.servicePojo.Message;
import team.cdlzz.model.servicePojo.SocketUser;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.ArrayList;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author zw
 * @date 2022-06-26.
 */
@ServerEndpoint("/upSocket/{uid}/cid/{cid}")
@Controller
public class UpWebSocketController {
//
    public static UserMapper userMapper;


    public static ConcurrentHashMap<Integer,ConcurrentHashMap<Session,SocketUser>>
            rooms = new ConcurrentHashMap<>();
//    private static ArrayList<SocketUser> userList = new ArrayList<>();

    public static ConcurrentHashMap<Integer,ArrayList<SocketUser>>
            mapList = new ConcurrentHashMap<>();

    //使用线程安全对象进行操作
//    private static ConcurrentHashMap<Session, SocketUser> sessionMapUser = new ConcurrentHashMap();

//    private static AtomicInteger onlineCount = new AtomicInteger(0);

    @OnOpen
    public void onOpen(Session session,@PathParam("uid") Integer name,@PathParam("cid")Integer cid) {
        System.out.println(name);
        User u = userMapper.selectByPrimaryKey(name);//获取到用户

        if (u!=null){   //如果验证成功,加入聊天室
            ConcurrentHashMap<Session, SocketUser> toSessionMapUser = getSessionMapUser(cid);//获取当前房间
            if (toSessionMapUser!=null){//如果房间存在
                AddRoom(cid,toSessionMapUser,session,u);
            }else { //如果房间不存在
                ConcurrentHashMap<Session, SocketUser> sessionSocketUserConcurrentHashMap = InitRoom(cid);
                AddRoom(cid,sessionSocketUserConcurrentHashMap,session,u);
            }
        }
    }

    private ConcurrentHashMap<Session, SocketUser> InitRoom(Integer cid){
        ConcurrentHashMap<Session, SocketUser> sessionSocketUserConcurrentHashMap = new ConcurrentHashMap<>();
        rooms.put(cid,sessionSocketUserConcurrentHashMap);//创建房间
        mapList.put(cid,new ArrayList<>());
        return sessionSocketUserConcurrentHashMap;
    }
    @OnClose
    public void onClose  (Session session,@PathParam("cid") Integer cid) {
        ConcurrentHashMap<Session, SocketUser> sessionMapUser = getSessionMapUser(cid);
        ArrayList<SocketUser> userListByCid = getUserListByCid(cid);
        SocketUser user = SessionGetUser(session,sessionMapUser);
        System.out.println(user.toString());
        UserClose(session,user,userListByCid,sessionMapUser);//在列表中删除用户
        SendClose(user,sessionMapUser);
    }

    @OnMessage
    public void onMessage(String message, Session session,@PathParam("cid")Integer cid) {
        System.out.println("来自房间 "+ cid +"的消息:"+message);
        Message m = JSONObject.parseObject(message, Message.class);
        ConcurrentHashMap<Session,SocketUser> concurrentHashMap = getSessionMapUser(cid);
//        SocketUser user = concurrentHashMap.get(session);
//        System.out.println("服务端收到客户端"+user.getUsername()+"的消息:"+ message);
        ConcurrentHashMap.KeySetView<Session, SocketUser> sessions = concurrentHashMap.keySet();
        for (Session key : sessions) {
            sendMessage(m,key);
        }
    }

    @OnError
    public void onError(Session session, Throwable error) {
        System.out.println("发生错误");
        error.printStackTrace();
    }


    /**
     * 发送单体消息
     * @param message
     * @param toSession
     */
    private void sendMessage(Message message, Session toSession) {
        try {
            String messageStr =JSONObject.toJSONString(message) ;
            System.out.println(messageStr);
            System.out.println(messageStr);
            toSession.getBasicRemote().sendText(messageStr);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * 发送群体消息
     * @param message
     */
    private void SendMessageAllUser(Message message,ConcurrentHashMap<Session, SocketUser> toSessionMapUser){
        ConcurrentHashMap.KeySetView<Session, SocketUser> sessions = toSessionMapUser.keySet();
        for (Session session : sessions){
            sendMessage(message,session);
        }
    }


    /**
     * 数据添加---加入用户
     *
     */
    private SocketUser addUser(Session session,User u,ConcurrentHashMap<Session, SocketUser> toSessionMapUser){
        SocketUser user = new SocketUser(u);
        toSessionMapUser.put(session,user);
        return user;
    }


    /**
     * 发送初始化数据
     * @param session
     * @param user
     */
    private void SendLoginInit(Session session , SocketUser user, ArrayList<SocketUser> userListByCid){
        Message message = Message.loginMessage(user,userListByCid);
        System.out.println(user.getUsername()+"--加入聊天室 ===="+"，当前在线人数为："+ (userListByCid.size()+1));
//        System.out.println(JSONObject.toJSONString(message));
        sendMessage(message,session);
    }


    /**
     * 用户加入队列 推送加入频道的消息
     * @param user
     */
    private void SendAddMessage(SocketUser user, ArrayList<SocketUser> userListByCid,ConcurrentHashMap<Session, SocketUser> toSessionMapUser){
        Message message = new Message(user,user.getUsername()+"加入了聊天室",1,null);
        userListByCid.add(user);
        SendMessageAllUser(message,toSessionMapUser);
    }

    private void UserClose(Session session, SocketUser user, ArrayList<SocketUser> userListByCid, ConcurrentHashMap<Session, SocketUser> sessionMapUser){
        sessionMapUser.remove(session);
        userListByCid.remove(user);
    }

    private void SendClose(SocketUser user, ConcurrentHashMap<Session, SocketUser> sessionMapUser){
        Message message = new Message(user, user.getUsername()+" -- 退出房间",2,null);
        SendMessageAllUser(message,sessionMapUser);
    }

    private SocketUser SessionGetUser(Session session,ConcurrentHashMap<Session,SocketUser> concurrentHashMap){
        return concurrentHashMap.get(session);
    }

    /**
     * 返回
     * @param cid
     * @return
     */
    private ConcurrentHashMap<Session,SocketUser> getSessionMapUser(Integer cid){
        ConcurrentHashMap<Session, SocketUser> sessionSocketUserConcurrentHashMap = rooms.get(cid);
        return sessionSocketUserConcurrentHashMap;
    }

    /**
     * 返回
     * @param cid
     * @return
     */
    private ArrayList<SocketUser> getUserListByCid(Integer cid){
        return mapList.get(cid);
    }

    /**
     * 加入房间的方法
     * @param cid 房间号
     * @param toSessionMapUser 房间用户列表
     * @param session 用户的会话
     * @param u 用户映射的信息
     */
    private void AddRoom(Integer cid ,ConcurrentHashMap toSessionMapUser,Session session,User u){
        ArrayList<SocketUser> userListByCid = getUserListByCid(cid);
        System.out.println("房间号为 === " + cid);
        SocketUser user = addUser(session,u,toSessionMapUser); //添加到聊天室队列---暂时不添加进入用户列表
        SendLoginInit(session,user,userListByCid);     //返回初始化数据
        SendAddMessage(user,userListByCid,toSessionMapUser);       //加入用户队列,发送用户加入
    }
}